using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Xml;

namespace Builder
{
  public partial class frmMain : Form
  {
    private List<BuildScreen> m_tsForms = new List<BuildScreen>();
    private System.Xml.XmlDocument m_XPData;
    private Dictionary<int, XPInfo> m_XPDataDict;
    private System.Windows.Forms.WebBrowser m_ImportWB;
    private const string PLAYERURLFILE = "url.xml";
    private const string PLAYERURLNODENAME = "PlayerUrl";
    private List<Archetype> m_Archetypes = null;
    
    public frmMain()
    {
      InitializeComponent();
      this.Text = this.ProductName + " v." + this.ProductVersion;
    }


    private void Form1_Load(object sender, EventArgs e)
    {
      cmbxGameDay.SelectedIndex = 0;
      String AppPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
      try
      {
        XmlDocument doc = new XmlDocument();
        doc.Load(System.IO.Path.Combine(AppPath, "archetypes.xml"));
        m_Archetypes = new List<Archetype>();
        foreach (XmlNode Position in doc.DocumentElement.ChildNodes)
        {
          foreach (XmlNode arType in Position.ChildNodes)
          {
            Archetype at = new Archetype(arType, Position.Name);
            m_Archetypes.Add(at);
          }
        }

        cmbxPosition.Items.Clear();
        foreach (Archetype at in m_Archetypes)
        {
          cmbxPosition.Items.Add(at);
        }
        cmbxPosition.DisplayMember = "DisplayName";
        cmbxPosition.ValueMember = "DisplayName";

        
      }
      catch (Exception ex)
      {
        MessageBox.Show("Unable to load Archetypes.  Error message: " + ex.Message);
      }


      if (System.IO.File.Exists(System.IO.Path.Combine(AppPath, "xp.xml")))
      {
        try
        {
          m_XPData = new System.Xml.XmlDocument();
          m_XPData.Load(System.IO.Path.Combine(AppPath, "xp.xml"));
          FillGrid();
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Unable read the required file 'xp.xml'.  Please download a new copy of this file.  If you have edited it manually, please restore an original copy.");
          this.Close();
        }
      }
      else
      {
        Utility.ShowWarningMessage("Unable to locate required file 'xp.xml'.  Please make sure this file exists with the application exe file.  The application will not run properly without it.", "File Not Found");
        this.Close();
      }

      //try to load the player URLs from the player URLs file
      try
      {
        if (System.IO.File.Exists(PLAYERURLFILE))
        {
          System.Xml.XmlDocument PlayerURLs = new System.Xml.XmlDocument();


          PlayerURLs.Load(PLAYERURLFILE);
          foreach (System.Xml.XmlNode node in PlayerURLs.SelectNodes("/players/" + PLAYERURLNODENAME))
          {
            cmbxPlayerURL.Items.Add(node.InnerText);
          }
        }
        else
        {
          using (System.IO.FileStream fs = System.IO.File.Create(PLAYERURLFILE))
          {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            Byte[] data = encoding.GetBytes("<players></players>");
            fs.Write(data, 0, data.Length);
            fs.Flush();
          }
        }
      }
      catch
      {
      }


    }

    /// <summary>
    /// Fills the XP grid
    /// </summary>
    private void FillGrid()
    {

      foreach (System.Xml.XmlNode mainnode in m_XPData)
      {
        foreach (System.Xml.XmlNode lvlNode in mainnode.ChildNodes)
        {
          if (lvlNode.Name == "XP")
          {
            DataGridViewRow dgvr = new DataGridViewRow();
            dgvr.CreateCells(dtgrdvwXP);
            foreach (System.Xml.XmlNode dataNode in lvlNode.ChildNodes)
            {
              try
              {
                //make sure these are only integers that are being imported
                if (dataNode.Name == "LVL")
                  dgvr.Cells[0].Value = int.Parse(dataNode.InnerText.ToString()).ToString();
                else if (dataNode.Name == "GXP")
                  dgvr.Cells[1].Value = int.Parse(dataNode.InnerText.ToString()).ToString();
                else
                  dgvr.Cells[2].Value = int.Parse(dataNode.InnerText.ToString()).ToString();
              }
              catch (Exception ex)
              {
                MessageBox.Show(string.Format("Error importing XP information line.  Bad value '{0}'.  Error message {1}", dataNode.InnerText.ToString(), ex.Message));
              }
            }
            dtgrdvwXP.Rows.Add(dgvr);
          }
        }
      }
    }

    private void btnSaveXPChanges_Click(object sender, EventArgs e)
    {
      try
      {

        System.Xml.XmlDocument NewXPData = new System.Xml.XmlDocument();
        System.Xml.XmlNode mainNode = NewXPData.CreateNode(System.Xml.XmlNodeType.Element, "LEVELDATA", "Builder");
        foreach (DataGridViewRow row in dtgrdvwXP.Rows)
        {
          //validate
          int tempTXP;
          int tempGXP;
          int tempLVL;
          if (!int.TryParse(row.Cells[2].Value.ToString(), out tempTXP))
          {
            Utility.ShowWarningMessage(string.Format("Training XP {0} in row level {1} is invalid", row.Cells[2].Value.ToString(), row.Cells[0].Value.ToString()), "Invalid Data");
            continue;
          }
          if (!int.TryParse(row.Cells[1].Value.ToString(), out tempGXP))
          {
            Utility.ShowWarningMessage(string.Format("Game XP {0} in row level {1} is invalid", row.Cells[1].Value.ToString(), row.Cells[0].Value.ToString()), "Invalid Data");
            continue;
          }
          if (!int.TryParse(row.Cells[0].Value.ToString(), out tempLVL))
          {
            Utility.ShowWarningMessage(string.Format("Level {1} is invalid in xp.xml file.", row.Cells[0].Value.ToString()), "Invalid Data");
            continue;
          }

          System.Xml.XmlNode XPNode = NewXPData.CreateNode(System.Xml.XmlNodeType.Element, "XP", "Builder");
          System.Xml.XmlNode TXPDataNode = NewXPData.CreateNode(System.Xml.XmlNodeType.Element, "TXP", "Builder");
          TXPDataNode.InnerText = tempTXP.ToString();
          System.Xml.XmlNode GXPDataNode = NewXPData.CreateNode(System.Xml.XmlNodeType.Element, "GXP", "Builder");
          GXPDataNode.InnerText = tempGXP.ToString();
          System.Xml.XmlNode LVLDataNode = NewXPData.CreateNode(System.Xml.XmlNodeType.Element, "LVL", "Builder");
          LVLDataNode.InnerText = tempLVL.ToString();
          XPNode.PrependChild(LVLDataNode);
          XPNode.PrependChild(GXPDataNode);
          XPNode.PrependChild(TXPDataNode);
          mainNode.PrependChild(XPNode);
        }
        NewXPData.PrependChild(mainNode);
        String AppPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
        NewXPData.Save(System.IO.Path.Combine(AppPath, "xp.xml"));
      }
      catch (Exception ex)
      {
        Utility.ShowErrorMesssage(ex, "Unable to save your XP Changes.");
      }
    }

    private void btnLoadNewXP_Click(object sender, EventArgs e)
    {
      if (openFileDialog1.ShowDialog() == DialogResult.OK)
      {
        try
        {
          m_XPData.Load(openFileDialog1.FileName);
          FillGrid();
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, string.Format("Unable to load XP data from file {0}", openFileDialog1.FileName));
        }
      }
    }

    private void btnCalculateLevel_Click(object sender, EventArgs e)
    {
      CalculateLevel();
    }

    private Boolean CalculateLevel()
    {
      Boolean Result = false;
      if (!BuildFormsOpen() || (MessageBox.Show("There are build forms open.  Continuing with the level calculation will close them and all work will be lost.  Continue?", "Build Forms Open", MessageBoxButtons.YesNo) == DialogResult.Yes))
      {
        DisposeBuildForms();
        LoadXPDataDict();
        try
        {
          //now that we've got the level data, calculate through this season.
          //int CurrentXP = (int)Math.Truncate(spnedtXP.Value);
          PlayerData RunningPlayerTotals = new PlayerData(1, (int)spnedtDay.Value, (int)spnedtXP.Value, (int)spnedtLevel.Value, (int)spnVXP.Value);
          int SPsEarnedToday = 0;
          dtgrdvwDailyData.Rows.Clear();


          while (RunningPlayerTotals.Season <= spnedtSeasons.Value)
          {
            while (RunningPlayerTotals.Day <= 39)
            {
              int VSPEarned = 0;
              int DailyVXP = 0;
              if ((int)spnBoostDay.Value == RunningPlayerTotals.Day)
              {
                RunningPlayerTotals.LevelXP += 1000;
                RunningPlayerTotals.LevelXP += 1000;
                RunningPlayerTotals.LevelXP += 1000;
              }
              //recalc level
              if (chckbxIncludeTodaysGame.Checked && Utility.GameToday(RunningPlayerTotals.Day, cmbxGameDay.Text) && RunningPlayerTotals.Day == spnedtDay.Value && RunningPlayerTotals.Season == 1 && RunningPlayerTotals.Day > 0)
              {
                int FirstGameXP = 100;
                if (m_XPDataDict.ContainsKey(RunningPlayerTotals.Level))
                {
                  FirstGameXP = m_XPDataDict[RunningPlayerTotals.Level].GameMaxXP;
                }
                FirstGameXP = (int)(Math.Truncate(FirstGameXP * (spnedtMaxGameXPPct.Value / 100)));
                RunningPlayerTotals.LevelXP += FirstGameXP;
                if (RunningPlayerTotals.LevelXP < FirstGameXP)
                {
                  SPsEarnedToday += 5;
                  //if we hit level 25 add the VSPs
                  if (RunningPlayerTotals.Level == 25)
                  {
                    VSPEarned = 2;
                  }
                }
                AddPlayerXPGridRow(0, FirstGameXP, 0, SPsEarnedToday, RunningPlayerTotals, 0, 0, 0);
              }
              else if (RunningPlayerTotals.Day == spnedtDay.Value && RunningPlayerTotals.Season == 1)
              {
                //add a placeholder row for today
                AddPlayerXPGridRow(0, 0, 0, 0, RunningPlayerTotals, 0, 0, 0);
              }
              RunningPlayerTotals.Day++;
              SPsEarnedToday = 0;
              DailyVXP = RunningPlayerTotals.DailyVXPEarned();
              RunningPlayerTotals.VXP += DailyVXP;
              if (RunningPlayerTotals.VXP - 1000 >= 0)
              {
                RunningPlayerTotals.VXP = RunningPlayerTotals.VXP - 1000;
                VSPEarned++;
              }

              //recalc level
              int DailyXP = 25;
              if (m_XPDataDict.ContainsKey(RunningPlayerTotals.Level))
              {
                DailyXP = m_XPDataDict[RunningPlayerTotals.Level].DailyXP;
              }
              RunningPlayerTotals.LevelXP += DailyXP;
              if (RunningPlayerTotals.LevelXP < DailyXP)
              {
                SPsEarnedToday += 5;
                //if we hit level 25 add the VSPs
                if (RunningPlayerTotals.Level == 25)
                {
                  VSPEarned = 2;
                }
              }
              //Get game XP
              int GameXP = 100;
              //if there's a game today, add xp for it as well
              if (Utility.GameToday(RunningPlayerTotals.Day, cmbxGameDay.Text))
              {
                if (m_XPDataDict.ContainsKey(RunningPlayerTotals.Level))
                {
                  GameXP = m_XPDataDict[RunningPlayerTotals.Level].GameMaxXP;
                }
                GameXP = (int)(Math.Truncate(GameXP * (spnedtMaxGameXPPct.Value / 100)));
                RunningPlayerTotals.LevelXP += GameXP;
                if (RunningPlayerTotals.LevelXP < GameXP)
                {
                  SPsEarnedToday += 5;
                }
              }
              else
              {
                GameXP = 0;
              }
              //add this day to the grid
              AddPlayerXPGridRow(DailyXP, GameXP, 2, SPsEarnedToday, RunningPlayerTotals, 0, DailyVXP, VSPEarned);
            }

            if ((int)spnBoostDay.Value == RunningPlayerTotals.Day)
            {
              RunningPlayerTotals.LevelXP += 1000;
              RunningPlayerTotals.LevelXP += 1000;
              RunningPlayerTotals.LevelXP += 1000;
            }
            //if we boosted to 25, add the 2 VSPs
            int VSPsEarned = 0;
            if (RunningPlayerTotals.Level >= 25 && RunningPlayerTotals.Level <= 27)
            {
              VSPsEarned = 2;
            }
            RunningPlayerTotals.Day = 0;
            RunningPlayerTotals.Season++;
            //add an empty row to the grid
            AddPlayerXPGridRow(0, 0, (int)spnOffSeasonTP.Value, 0, RunningPlayerTotals, 3, 0, VSPsEarned);
          }
          Result = true;
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Unable to calculate player leveling information.");
        }
      }
      return Result;
    }

    /// <summary>
    /// true if there are build forms open, false otherwise.
    /// </summary>
    /// <returns></returns>
    private bool BuildFormsOpen()
    {
      Boolean Result = false;
      if (m_tsForms.Count > 0)
      {
        foreach (BuildScreen bs in m_tsForms)
        {
          if (bs != null && !bs.IsDisposed)
          {
            Result = true;
            break;
          }
        }
      }
      return Result;
    }

    /// <summary>
    /// Loads XP Data from the XP Data Grid View
    /// </summary>
    private void LoadXPDataDict()
    {
      if (m_XPDataDict == null)
        m_XPDataDict = new Dictionary<int, XPInfo>();
      m_XPDataDict.Clear();
      try
      {
        foreach (DataGridViewRow Row in dtgrdvwXP.Rows)
        {
          XPInfo toadd = new XPInfo();
          toadd.DailyXP = int.Parse(Row.Cells[2].Value.ToString());
          toadd.GameMaxXP = int.Parse(Row.Cells[1].Value.ToString());
          m_XPDataDict.Add(int.Parse(Row.Cells[0].Value.ToString()), toadd);
        }
      }
      catch (Exception ex)
      {
        Utility.ShowErrorMesssage(ex, "There are invalid values in your Daily and Game XP grid.  Please correct these or restart the application.");
      }
    }

    /// <summary>
    /// disposes of open build forms and clears the m_tsForms list.
    /// </summary>
    private void DisposeBuildForms()
    {
      foreach (BuildScreen bs in m_tsForms)
      {
        if (bs != null && !bs.IsDisposed)
        {
          bs.Dispose();
        }
      }
      m_tsForms.Clear();
    }

    private Boolean AddPlayerXPGridRow(int DailyXP, int GameXP, int TrainingPointsEarned, int SkillPointsEarned, PlayerData pd, int Boosts, int DailyVXP, int VSPEarned)
    {
      DataGridViewRow dgvr = new DataGridViewRow();
      dgvr.CreateCells(dtgrdvwDailyData);
      DataGridViewCellStyle dtgrdvwCellStyle = new DataGridViewCellStyle();
      dtgrdvwCellStyle.BackColor = Color.LightGreen;
      dgvr.Cells[0].Value = pd.Season.ToString() + "-" + pd.Day.ToString();
      dgvr.Cells[1].Value = DailyXP.ToString();
      dgvr.Cells[2].Value = GameXP.ToString();
      //total XP
      dgvr.Cells[3].Value = (pd.LevelXP + ((pd.Level - 1) * 1000)).ToString();
      //Daily VXP
      dgvr.Cells[4].Value = DailyVXP.ToString();
      //VXP
      dgvr.Cells[5].Value = pd.VXP.ToString();
      dgvr.Cells[6].Value = pd.Level.ToString();
      dgvr.Cells[7].Value = TrainingPointsEarned.ToString();
      dgvr.Cells[8].Value = SkillPointsEarned.ToString();
      if (SkillPointsEarned > 0)
      {
        dgvr.Cells[8].Style = dtgrdvwCellStyle;
        //color the cell that pushed player over the level hump
        if (pd.LevelXP - GameXP > 0)
        {
          dgvr.Cells[1].Style = dtgrdvwCellStyle;
        }
        else
        {
          dgvr.Cells[2].Style = dtgrdvwCellStyle;
        }
      }
      dgvr.Cells[9].Value = DateTime.Now.AddDays(dtgrdvwDailyData.Rows.Count).ToShortDateString();
      dgvr.Cells[10].Value = Boosts.ToString();
      dgvr.Cells[11].Value = VSPEarned.ToString();
      dtgrdvwDailyData.Rows.Add(dgvr);
      return true;
    }

    private void btnTrain_Click(object sender, EventArgs e)
    {
      if (cmbxPosition.Text.Trim() != "")
      {
        /*
         * Create a new Player Build screen.
         * Cycle through each day on the experience grid starting at the top
         * Allow a user to use any TP or SP still available on that day.
         * When leve
         */
        #region Get Attributes
        Dictionary<string, GLBAttribute> PlayerAttributes = new Dictionary<string, GLBAttribute>();
        if (lblStr.BackColor == Color.Green)
          PlayerAttributes.Add("strength", new GLBAttribute("strength", (double)nmrcudStr.Value, (int)spnPctStr.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblStr.BackColor == Color.Blue)
          PlayerAttributes.Add("strength", new GLBAttribute("strength", (double)nmrcudStr.Value, (int)spnPctStr.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("strength", new GLBAttribute("strength", (double)nmrcudStr.Value, (int)spnPctStr.Value, GLBAttribute.AttributeType.atNone));


        if (lblBlk.BackColor == Color.Green)
          PlayerAttributes.Add("blocking", new GLBAttribute("blocking", (double)nmrcudBlk.Value, (int)spnPctBlk.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblBlk.BackColor == Color.Blue)
          PlayerAttributes.Add("blocking", new GLBAttribute("blocking", (double)nmrcudBlk.Value, (int)spnPctBlk.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("blocking", new GLBAttribute("blocking", (double)nmrcudBlk.Value, (int)spnPctBlk.Value, GLBAttribute.AttributeType.atNone));


        if (lblSpd.BackColor == Color.Green)
          PlayerAttributes.Add("speed", new GLBAttribute("speed", (double)nmrcudSpd.Value, (int)spnPctSpd.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblSpd.BackColor == Color.Blue)
          PlayerAttributes.Add("speed", new GLBAttribute("speed", (double)nmrcudSpd.Value, (int)spnPctSpd.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("speed", new GLBAttribute("speed", (double)nmrcudSpd.Value, (int)spnPctSpd.Value, GLBAttribute.AttributeType.atNone));


        if (lbltck.BackColor == Color.Green)
          PlayerAttributes.Add("tackling", new GLBAttribute("tackling", (double)nmrcudTck.Value, (int)spnPctTck.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lbltck.BackColor == Color.Blue)
          PlayerAttributes.Add("tackling", new GLBAttribute("tackling", (double)nmrcudTck.Value, (int)spnPctTck.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("tackling", new GLBAttribute("tackling", (double)nmrcudTck.Value, (int)spnPctTck.Value, GLBAttribute.AttributeType.atNone));

        if (lblAgi.BackColor == Color.Green)
          PlayerAttributes.Add("agility", new GLBAttribute("agility", (double)nmrcudAgi.Value, (int)spnPctAgi.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblAgi.BackColor == Color.Blue)
          PlayerAttributes.Add("agility", new GLBAttribute("agility", (double)nmrcudAgi.Value, (int)spnPctAgi.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("agility", new GLBAttribute("agility", (double)nmrcudAgi.Value, (int)spnPctAgi.Value, GLBAttribute.AttributeType.atNone));


        if (lblThr.BackColor == Color.Green)
          PlayerAttributes.Add("throwing", new GLBAttribute("throwing", (double)nmrcudThr.Value, (int)spnPctThr.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblThr.BackColor == Color.Blue)
          PlayerAttributes.Add("throwing", new GLBAttribute("throwing", (double)nmrcudThr.Value, (int)spnPctThr.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("throwing", new GLBAttribute("throwing", (double)nmrcudThr.Value, (int)spnPctThr.Value, GLBAttribute.AttributeType.atNone));


        if (lblJum.BackColor == Color.Green)
          PlayerAttributes.Add("jumping", new GLBAttribute("jumping", (double)nmrcudJum.Value, (int)spnPctJum.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblJum.BackColor == Color.Blue)
          PlayerAttributes.Add("jumping", new GLBAttribute("jumping", (double)nmrcudJum.Value, (int)spnPctJum.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("jumping", new GLBAttribute("jumping", (double)nmrcudJum.Value, (int)spnPctJum.Value, GLBAttribute.AttributeType.atNone));


        if (lblCat.BackColor == Color.Green)
          PlayerAttributes.Add("catching", new GLBAttribute("catching", (double)nmrcudCat.Value, (int)spnPctCat.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblCat.BackColor == Color.Blue)
          PlayerAttributes.Add("catching", new GLBAttribute("catching", (double)nmrcudCat.Value, (int)spnPctCat.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("catching", new GLBAttribute("catching", (double)nmrcudCat.Value, (int)spnPctCat.Value, GLBAttribute.AttributeType.atNone));


        if (lblsta.BackColor == Color.Green)
          PlayerAttributes.Add("stamina", new GLBAttribute("stamina", (double)nmrcudSta.Value, (int)spnPctSta.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblsta.BackColor == Color.Blue)
          PlayerAttributes.Add("stamina", new GLBAttribute("stamina", (double)nmrcudSta.Value, (int)spnPctSta.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("stamina", new GLBAttribute("stamina", (double)nmrcudSta.Value, (int)spnPctSta.Value, GLBAttribute.AttributeType.atNone));


        if (lblCar.BackColor == Color.Green)
          PlayerAttributes.Add("carrying", new GLBAttribute("carrying", (double)nmrcudCar.Value, (int)spnPctCar.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblCar.BackColor == Color.Blue)
          PlayerAttributes.Add("carrying", new GLBAttribute("carrying", (double)nmrcudCar.Value, (int)spnPctCar.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("carrying", new GLBAttribute("carrying", (double)nmrcudCar.Value, (int)spnPctCar.Value, GLBAttribute.AttributeType.atNone));


        if (lblVis.BackColor == Color.Green)
          PlayerAttributes.Add("vision", new GLBAttribute("vision", (double)nmrcudVis.Value, (int)spnPctVis.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblVis.BackColor == Color.Blue)
          PlayerAttributes.Add("vision", new GLBAttribute("vision", (double)nmrcudVis.Value, (int)spnPctVis.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("vision", new GLBAttribute("vision", (double)nmrcudVis.Value, (int)spnPctVis.Value, GLBAttribute.AttributeType.atNone));


        if (lblKck.BackColor == Color.Green)
          PlayerAttributes.Add("kicking", new GLBAttribute("kicking", (double)nmrcudKck.Value, (int)spnPctKck.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblKck.BackColor == Color.Blue)
          PlayerAttributes.Add("kicking", new GLBAttribute("kicking", (double)nmrcudKck.Value, (int)spnPctKck.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("kicking", new GLBAttribute("kicking", (double)nmrcudKck.Value, (int)spnPctKck.Value, GLBAttribute.AttributeType.atNone));


        if (lblCon.BackColor == Color.Green)
          PlayerAttributes.Add("confidence", new GLBAttribute("confidence", (double)nmrcudCon.Value, (int)spnPctCon.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblCon.BackColor == Color.Blue)
          PlayerAttributes.Add("confidence", new GLBAttribute("confidence", (double)nmrcudCon.Value, (int)spnPctCon.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("confidence", new GLBAttribute("confidence", (double)nmrcudCon.Value, (int)spnPctCon.Value, GLBAttribute.AttributeType.atNone));


        if (lblPun.BackColor == Color.Green)
          PlayerAttributes.Add("punting", new GLBAttribute("punting", (double)nmrcudPun.Value, (int)spnPctPun.Value, GLBAttribute.AttributeType.atPrimary));
        else if (lblPun.BackColor == Color.Blue)
          PlayerAttributes.Add("punting", new GLBAttribute("punting", (double)nmrcudPun.Value, (int)spnPctPun.Value, GLBAttribute.AttributeType.atSecondary));
        else
          PlayerAttributes.Add("punting", new GLBAttribute("punting", (double)nmrcudPun.Value, (int)spnPctPun.Value, GLBAttribute.AttributeType.atNone));
        #endregion

        PlayerBuild pb = new PlayerBuild(1, (int)spnedtLevel.Value, (int)spnedtXP.Value, (int)spnedtDay.Value,
                                         (int)spnedtMaxGameXPPct.Value, (int)spnedtUnspentSP.Value,
                                         (int)spnedtUnspentTP.Value, (int)spnUnspentBTs.Value, (int)spnUnspentBoosts.Value,
                                         (int)spnPreSeasonTP.Value, (int)spnOffSeasonTP.Value, chckbxIncludeTodaysGame.Checked, cmbxGameDay.Text,
                                         (int)spnVXP.Value, (int)spnUnspentVSP.Value, lblName.Text);


        //Add initial base day
        PlayerDay InitDay = new PlayerDay(0, 0, (int)spnedtDay.Value, 0, 0, 0, 0, (int)spnUnspentBoosts.Value, PlayerAttributes);
        pb.PlayerDays.Add(Utility.GetSeasonDayString(0, (int)spnedtDay.Value), InitDay);
        //now add first actual working day.  Make sure to copy the attributes and not simply pass the same reference to them!
        pb.PlayerDays.Add(Utility.GetSeasonDayString(1, (int)spnedtDay.Value), new PlayerDay(0, 0, (int)spnedtDay.Value, 1, 0, 0, 0, 0, InitDay.GetCopyOfRunningBuildTotals()));

        try
        {
          BuildScreen BS = new BuildScreen();
          m_tsForms.Add(BS);
          BS.Initialize(pb);
          BS.Show();
        }
        catch (Exception ex)
        {
          MessageBox.Show(string.Format("Error creating a build form.  Error message: {0}", ex.Message), "Error", MessageBoxButtons.OK);
        }
      }
      else
      {
        MessageBox.Show("You must first select a position", "Select a Position", MessageBoxButtons.OK);
        cmbxPosition.Focus();
      }
    }

    private void Form1_FormClosed(object sender, FormClosedEventArgs e)
    {
      DisposeBuildForms();
    }

    #region Player IMport Functionality
    //Added code to completely remove double quotes
    private void btnPaste_Click(object sender, EventArgs e)
    {
      using (PastePageSource pi = new PastePageSource())
      {
        if (pi.ShowDialog() == DialogResult.OK)
        {
          ParsePlayerScreen(pi.m_PlayerScreenHtml.ToLower());
        }
      }
    }

    private void btnNavigate_Click(object sender, EventArgs e)
    {
      int PlayerNumber = 0;
      if (int.TryParse(cmbxPlayerURL.Text, out PlayerNumber))
      {
        cmbxPlayerURL.Text = string.Format("http://goallineblitz.com/game/player.pl?player_id={0}", PlayerNumber);
      }
      using (PlayerImport pi = new PlayerImport(cmbxPlayerURL.Text))
      {
        if (pi.ShowDialog() == DialogResult.OK)
        {
          if (pi.m_StorePlayerURL && cmbxPlayerURL.Items.IndexOf(pi.m_PlayerUrl) < 0)
          {
            SavePlayerURL(pi.m_PlayerUrl);
          }
          ParsePlayerScreen(pi.m_PlayerScreenHtml.ToLower());
        }
      }
    }

    private void SavePlayerURL(string Url)
    {
      try
      {
        cmbxPlayerURL.Items.Add(Url);
        System.Xml.XmlDocument PlayerURLs = new System.Xml.XmlDocument();
        PlayerURLs.Load(PLAYERURLFILE);
        System.Xml.XmlNode newPlayer = PlayerURLs.CreateNode(System.Xml.XmlNodeType.Element, PLAYERURLNODENAME, "");
        newPlayer.InnerText = Url;
        PlayerURLs.DocumentElement.AppendChild(newPlayer);
        PlayerURLs.Save(PLAYERURLFILE);
      }
      catch (Exception ex)
      {
        Utility.ShowErrorMesssage(ex, "Unable to save URL to history.");
      }
    }


    private void ParsePlayerScreen(string playerScreenHTML)
    {
      try
      {
        SetAttributeValues("strength", playerScreenHTML);
        SetAttributeValues("blocking", playerScreenHTML);
        SetAttributeValues("speed", playerScreenHTML);
        SetAttributeValues("tackling", playerScreenHTML);
        SetAttributeValues("agility", playerScreenHTML);
        SetAttributeValues("carrying", playerScreenHTML);
        SetAttributeValues("jumping", playerScreenHTML);
        SetAttributeValues("catching", playerScreenHTML);
        SetAttributeValues("stamina", playerScreenHTML);
        SetAttributeValues("throwing", playerScreenHTML);
        SetAttributeValues("vision", playerScreenHTML);
        SetAttributeValues("kicking", playerScreenHTML);
        SetAttributeValues("confidence", playerScreenHTML);
        SetAttributeValues("punting", playerScreenHTML);
        SetAttributeValues("level", playerScreenHTML);
        SetXPValue(playerScreenHTML);
        SetPlayerPointsValue(playerScreenHTML);
        SetPlayerPos(playerScreenHTML);
        if (chckbxImportSAs.Checked)
        {
          int TreeMaxIndex = 2;
          int AttrMaxIndex = 5;
          if (cmbxPosition.Text == "Kicker" || cmbxPosition.Text == "Punter")
          {
            TreeMaxIndex = 1;
            AttrMaxIndex = 3;
          }

          for (int i = 1; i <= TreeMaxIndex; i++)
          {
            for (int j = 1; j <= AttrMaxIndex; j++)
              SetSAValues(i, j, playerScreenHTML);
          }
        }
        SetPlayerName(playerScreenHTML);
        SetVeteranSP(playerScreenHTML);
      }
      catch (Exception e)
      {
        Utility.ShowErrorMesssage(e, "An error occurred attempting to import your player's data.");
      }
      //get level and XP
    }

    private void SetVeteranSP(string playerScreenHTML)
    {
      int VSPLinkStartPos = playerScreenHTML.IndexOf("/game/vet_skills.pl?");
      if (VSPLinkStartPos < 0)
      {
        return;
      }
      int VSPStartPos = playerScreenHTML.IndexOf(">", VSPLinkStartPos);
      int VSPEndPos = playerScreenHTML.IndexOf("<", VSPStartPos);
      if (VSPStartPos > 0 && VSPEndPos > VSPStartPos)
      {
        //pull off all digits to the left of XP End Position.
        try
        {
          string VSP = playerScreenHTML.Substring(VSPStartPos + 1, VSPEndPos - (VSPStartPos + 1)).Trim();
          int ForSlashPos = VSP.IndexOf("/");
          if (ForSlashPos > 0)
          {
            VSP = VSP.Substring(0, ForSlashPos);
          }
          spnUnspentVSP.Value = int.Parse(VSP);
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Error retrieving VSP value.  Please set it manually");
          spnUnspentVSP.Value = 0;
        }
      }
      else
      {
        spnUnspentVSP.Value = 0;
      }
    }

    private void SetPlayerName(string playerScreenHTML)
    {
      //player_name
      string statValue = "";

      int AttrPos = playerScreenHTML.IndexOf("big_head subhead_head");
      if (AttrPos >= 0)
      {
        try
        {
          int statStartPos = playerScreenHTML.IndexOf(">", AttrPos, 30);
          //find the following close paren bracket <
          int statEndPos = playerScreenHTML.IndexOf("<", statStartPos, 200);
          if (statStartPos < statEndPos && statEndPos > 0)
          {
            lblName.Text = playerScreenHTML.Substring(statStartPos + 1, (statEndPos - 1) - statStartPos);
          }
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Error retrieving player's name");
        }
      }
    }

    private void SetPlayerPointsValue(string playerScreenHTML)
    {
      //search for "player_points_value".  From there, the next line is a series of table cells with
      //Level, Skill Points, TP, BT, Shop Tokens. For example:
      //<td>39</td><td>0</td><td>4</td><td>3</td><td>0</td>
      //We need to parse this out and get the values.
      int PlayerPtsPos = playerScreenHTML.IndexOf("player_points_value");
      if (PlayerPtsPos >= 0)
      {
        //From there, pull the next 150 characters
        string Data = playerScreenHTML.Substring(PlayerPtsPos, 150).Replace("\r", string.Empty);
        Data = Data.Replace("\n", string.Empty);
        string[] Delimiters = { "<td>", "</td>" };
        string[] StatsArray = Data.Split(Delimiters, StringSplitOptions.RemoveEmptyEntries);

        try
        {
          //index 0 is garbage.
          //index 1 is level,
          spnedtLevel.Value = int.Parse(StatsArray[1]);
          //index 2 is skill points,
          spnedtUnspentSP.Value = int.Parse(StatsArray[2]);
          //index 3 is TP,
          spnedtUnspentTP.Value = int.Parse(StatsArray[3]);
          //index 4 is BT
          spnUnspentBTs.Value = int.Parse(StatsArray[4]);


        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Error attempting to pull Player's level, skill points, training points and bonus tokens.  Please set these manually");
        }
      }
      else
      {
        Utility.ShowWarningMessage("Unable to retreive Level, Unspent Skill Points, Unspent Training Points and Bonus Tokens.  Please set these manually.", "Warning");
      }
    }


    private void SetAttributeValues(string Attr, string playerScreenHTML)
    {
      //OK, we want to look for each stat specifically by name, using a capital first letter and a colon:
      //        "Strength:"
      //and then pull the next "class=stat_value".  Do not use "class=stat_value_boosted" b/c this is a value with equipment.  Pop up a message in this case.
      // eg: "class=stat_value>28.3"
      //immediately after that, we look for "training progress:" e.g. "training progress: 60%"         
      int AttrPos = -1;
      int TrainingPos = -1;

      #region Attribute Specific handling
      try
      {
        switch (Attr)
        {
          case "strength":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("strength:");
              TrainingPos = playerScreenHTML.IndexOf("strength training progress:");
              TrainingPos += 27;
              SetAttributeValue("strength", AttrPos, playerScreenHTML, nmrcudStr);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctStr);
            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing Strength AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "blocking":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("blocking:");
              TrainingPos = playerScreenHTML.IndexOf("blocking training progress:");
              TrainingPos += 27;
              SetAttributeValue("blocking", AttrPos, playerScreenHTML, nmrcudBlk);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctBlk);
            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing blocking AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "speed":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("speed:");
              TrainingPos = playerScreenHTML.IndexOf("speed training progress:");
              TrainingPos += 24;
              SetAttributeValue("speed", AttrPos, playerScreenHTML, nmrcudSpd);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctSpd);
            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing Speed AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "tackling":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("tackling:");
              TrainingPos = playerScreenHTML.IndexOf("tackling training progress:");
              TrainingPos += 27;
              SetAttributeValue("tackling", AttrPos, playerScreenHTML, nmrcudTck);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctTck);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing tackling AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "agility":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("agility:");
              TrainingPos = playerScreenHTML.IndexOf("agility training progress:");
              TrainingPos += 26;
              SetAttributeValue("agility", AttrPos, playerScreenHTML, nmrcudAgi);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctAgi);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing agility AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "carrying":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("carrying:");
              TrainingPos = playerScreenHTML.IndexOf("carrying training progress:");
              TrainingPos += 27;
              SetAttributeValue("carrying", AttrPos, playerScreenHTML, nmrcudCar);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctCar);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing carry AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "jumping":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("jumping:");
              TrainingPos = playerScreenHTML.IndexOf("jumping training progress:");
              TrainingPos += 26;
              SetAttributeValue("jumping", AttrPos, playerScreenHTML, nmrcudJum);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctJum);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing jump AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "catching":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("catching:");
              TrainingPos = playerScreenHTML.IndexOf("catching training progress:");
              TrainingPos += 27;
              SetAttributeValue("catching", AttrPos, playerScreenHTML, nmrcudCat);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctCat);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing catching AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "stamina":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("stamina:");
              TrainingPos = playerScreenHTML.IndexOf("stamina training progress:");
              TrainingPos += 26;
              SetAttributeValue("stamina", AttrPos, playerScreenHTML, nmrcudSta);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctSta);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing stamina AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "throwing":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("throwing:");
              TrainingPos = playerScreenHTML.IndexOf("throwing training progress:");
              TrainingPos += 27;
              SetAttributeValue("throwing", AttrPos, playerScreenHTML, nmrcudThr);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctThr);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing throw AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "vision":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("vision:");
              TrainingPos = playerScreenHTML.IndexOf("vision training progress:");
              TrainingPos += 25;
              SetAttributeValue("vision", AttrPos, playerScreenHTML, nmrcudVis);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctVis);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing vision AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "kicking":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("kicking:");
              TrainingPos = playerScreenHTML.IndexOf("kicking training progress:");
              TrainingPos += 26;
              SetAttributeValue("kicking", AttrPos, playerScreenHTML, nmrcudKck);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctKck);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing kicking AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "confidence":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("confidence:");
              TrainingPos = playerScreenHTML.IndexOf("confidence training progress:");
              TrainingPos += 29;
              SetAttributeValue("confidence", AttrPos, playerScreenHTML, nmrcudCon);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctCon);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing confidence AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
          case "punting":
            try
            {
              AttrPos = playerScreenHTML.IndexOf("punting:");
              TrainingPos = playerScreenHTML.IndexOf("punting training progress:");
              TrainingPos += 26;
              SetAttributeValue("punting", AttrPos, playerScreenHTML, nmrcudPun);
              SetTrainingPct(TrainingPos, playerScreenHTML, spnPctPun);

            }
            catch (Exception E)
            {
              Utility.SaveErrorInformation(E, String.Format("While Doing punting AttrPos={0}, TrainingPos={1}, playerScreenHtml={2}", AttrPos, TrainingPos, playerScreenHTML));
            }
            break;
        }
      }
      catch (Exception ex)
      {
        Utility.ShowErrorMesssage(ex, "Error attempting to parse your player's GLB page.");
      }
      #endregion
    }

    private void SetAttributeValue(string AttributeName, int AttrPos, string playerScreenHTML, NumericUpDown control)
    {
      string statValue = "8";
      if (AttrPos >= 0)
      {
        try
        {
          int BoostedPos = playerScreenHTML.IndexOf("stat_value_tall_boosted", AttrPos, 60);
          int statValPos = playerScreenHTML.IndexOf("stat_value_tall", AttrPos, 60);
          if (BoostedPos > 0)
          {
            //find the following close bracket >
            int BoostedStatStartPos = playerScreenHTML.IndexOf(">", statValPos, 40);
            //find the following Space
            int BoostedStatEndPos = playerScreenHTML.IndexOf(" ", statValPos, 40);
            int BoostAmountStartPos = playerScreenHTML.IndexOf("(", statValPos, 40);
            int BoostAmountEndPos = playerScreenHTML.IndexOf(")", statValPos, 40);
            if (BoostedStatStartPos > 0 && BoostAmountStartPos > 0 &&
                BoostAmountStartPos < BoostAmountEndPos && BoostedStatStartPos < BoostedStatEndPos)
            {
              string BoostedStatValueStr = playerScreenHTML.Substring(BoostedStatStartPos + 1, BoostedStatEndPos - (BoostedStatStartPos + 1));
              string BoostValueStr = playerScreenHTML.Substring(BoostAmountStartPos + 1, BoostAmountEndPos - (BoostAmountStartPos + 1));
              BoostValueStr = BoostValueStr.Replace("+", String.Empty);
              double BoostedStatValue = 0;
              double BoostValue = 0;
              if (double.TryParse(BoostedStatValueStr, out BoostedStatValue) &&
                  double.TryParse(BoostValueStr, out BoostValue))
              {
                statValue = (BoostedStatValue - BoostValue).ToString();
              }
              else
              {
                Utility.ShowInfoMessage(String.Format("Unable to parse value for {0}.  Please set it manually to it's natural level for proper modeling", AttributeName), "Modified Attribute Warning");
              }
            }
            else
            {
              Utility.ShowInfoMessage(String.Format("Unable to parse value for {0}.  Please set it manually to it's natural level for proper modeling", AttributeName), "Modified Attribute Warning");
            }
          }
          else if (statValPos > 0)
          {
            //find the following close bracket >
            int statStartPos = playerScreenHTML.IndexOf(">", statValPos, 30);
            //find the following open bracket <
            int statEndPos = playerScreenHTML.IndexOf("<", statValPos, 30);
            if (statEndPos > 0)
            {
              statValue = playerScreenHTML.Substring(statStartPos + 1, statEndPos - (statStartPos + 1));
            }
          }
          else
          {
            Utility.ShowInfoMessage(String.Format("Unable to parse value for {0}.  Please set it manually to it's natural level for proper modeling", AttributeName), "Modified Attribute Warning");
          }
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, string.Format("Error retrieving {0}.", AttributeName));
          statValue = "8";
        }
      }

      double AttrValue = 0;
      System.Globalization.NumberStyles style;
      System.Globalization.CultureInfo culture;
      style = System.Globalization.NumberStyles.Number;
      culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
      //culture = System.Globalization.CultureInfo.CreateSpecificCulture("es-ES");



      if (!double.TryParse(statValue, style, culture, out AttrValue))
      {
        control.Value = 8;
      }
      else
      {
        control.Value = Math.Round((decimal)AttrValue, 2);
      }
    }

    #region SA Parsing
    /// <summary>
    /// Iterates the player's profile HTML string to find the value for a specific SA on a
    /// specific tree.
    /// </summary>
    /// <param name="tree">Integer.  Represents the SA tree.  Allowed values are 1 and 2.</param>
    /// <param name="SA">Integer.  Represents the SA within a tree by position.  Allowed
    ///                  values are 1, 2, 3, 4, and 5.</param>
    /// <param name="playerScreenHTML">String.  The raw HTML source of the player's page.</param>
    private void SetSAValues(int tree, int SA, string playerScreenHTML)
    {
      /*  SAs are contained within the <div id="player_skill_trees"> tag.  Since the tag names
       *  within this tag will differ based on player position, we'll have to use some more
       *  creative parsing to find the one we want.
       * 
       *  Within the player_skill_trees div are two, possibly three <div class="subhead"> tags
       *  that represent the two standard trees and the possible extra "Additional Abilities"
       *  tree.  Additional Abilities only come through AE and therefore can be ignored for
       *  our purposes.  Therefore, our first task is to find the correct tree for the SA.
       * 
       *  Within each subhead are five <div class="skill_level" id="skill_level_SA_NAME> tags, 
       *  each of which represents an individual SA.  Since these will vary from position to  
       *  position, we can't use strict parsing positions to figure out the values.  Instead, we 
       *  must find the value between the closing bracket ">" and the opening bracket of the 
       *  closing </div> tag "<" to get our value.  This is done in SetSAValue().  Here we just
       *  find the SA string fragment to pass along.
       * 
       *  TODO:  Error checking code.
       */
      int SAPos = -1;
      int EndPos = -1;
      string SAString;

      SAPos = playerScreenHTML.IndexOf("<div id=\"player_skill_trees\">"); //Puts us to the right section

      for (int i = 0; i < tree; i++)
        SAPos = playerScreenHTML.IndexOf("<div class=\"subhead\">", SAPos + 1); //Puts us to the right tree

      for (int i = 0; i < SA; i++)
        SAPos = playerScreenHTML.IndexOf("<div class=\"skill_button\"", SAPos + 1); //Puts us to the right SA

      EndPos = playerScreenHTML.IndexOf("</div></div>", SAPos) + 12;
      SAString = playerScreenHTML.Substring(SAPos, EndPos - SAPos);

      Control[] ctrls = this.Controls.Find("spnTree" + tree.ToString() + "SA" + SA.ToString(), true);

      SetSAValue(SA, tree, SAString, (NumericUpDown)ctrls[0]);
    }

    /// <summary>
    /// Searches a substring of playerScreenHTML for the value of an SA.
    /// </summary>
    /// <param name="SA">Integer.  The specific SA within a tree being searched for.</param>
    /// <param name="tree">Integer.  The SA tree that the SA belongs to.</param>
    /// <param name="SAString">HTML fragment specific to the SA.</param>
    /// <param name="control">The NumericUpDown control to attach the value to.</param>
    private void SetSAValue(int SA, int tree, string SAString, NumericUpDown control)
    {
      /*
       *  TODO: Error checking code
       */
      int StartPos = -1;
      int EndPos = -1;
      int SAValue = 0;

      if (SAString.IndexOf("skill_level boosted_skill_level") > -1) //Boosted SA detection
        Utility.ShowInfoMessage(String.Format("Tree {0}, SA {1} appears to be a modified SA.  Please set it manually to its natural level for proper modeling", tree.ToString(), SA.ToString()), "Modified SA Warning");
      else
      {
        StartPos = SAString.IndexOf(" id=\"skill_level_"); //Puts us to the right SA
        StartPos = SAString.IndexOf(">", ++StartPos);
        EndPos = SAString.IndexOf("<", ++StartPos);
        SAValue = Convert.ToInt32(SAString.Substring(StartPos, EndPos - StartPos));
      }
      control.Value = Convert.ToDecimal(SAValue);
    }
    #endregion

    private void SetXPValue(string playerScreenHTML)
    {
      int XPEndPos = playerScreenHTML.IndexOf("/1000");
      int XPStartPos = playerScreenHTML.IndexOf("next level:");
      if (XPEndPos > 0 && XPEndPos > XPStartPos)
      {
        //pull off all digits to the left of XP End Position.
        try
        {
          int Index = XPEndPos;
          string strValue = string.Empty;
          while (Index > XPStartPos)
          {
            Index--;
            if (Char.IsNumber(playerScreenHTML[Index]))
            {
              strValue = playerScreenHTML[Index] + strValue;
            }
            else
            {
              break;
            }
          }
          spnedtXP.Value = int.Parse(strValue);
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Error retrieving XP value.  Please set it manually");
          spnedtXP.Value = 0;
        }
      }
    }

    private void SetPlayerPos(string playerScreenHTML)
    {
      //player_name
      string statValue = "";

      int AttrPos = playerScreenHTML.IndexOf("\"position ");
      if (AttrPos >= 0)
      {
        try
        {
          int statStartPos = playerScreenHTML.IndexOf(">", AttrPos, 100);
          //find the following close paren bracket <
          int statEndPos = playerScreenHTML.IndexOf("<", statStartPos, 5);
          if (statEndPos > 0)
          {
            String Pos = playerScreenHTML.Substring(statStartPos + 1, statEndPos - (statStartPos + 1));

            foreach (Archetype at in m_Archetypes)
            {
              if (at.Link.ToLower() == Pos)
              {
                cmbxPosition.SelectedItem = at;
                break;
              }
            }            
          }
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Error retrieving player's position");
        }
      }
    }


    private void SetTrainingPct(int TraingPos, string playerScreenHTML, NumericUpDown control)
    {
      string statValue = "0";
      if (TraingPos >= 0)
      {
        try
        {
          int PctLoc = playerScreenHTML.IndexOf("%", TraingPos, 5);
          if (PctLoc > 0)
          {
            statValue = playerScreenHTML.Substring(TraingPos, PctLoc - TraingPos);
          }
        }
        catch (Exception ex)
        {
          Utility.ShowErrorMesssage(ex, "Error retrieving training value(s)." + ex.Message);
          statValue = "0";
        }
      }

      int TrValue = 0;
      if (!int.TryParse(statValue, out TrValue))
      {
        control.Value = 8;
      }
      else
      {
        control.Value = TrValue;
      }
    }
    #endregion

    #region Random UI Event Handlers
    private void cmbxPosition_SelectedIndexChanged(object sender, EventArgs e)
    {
      #region Clear
      lblStr.ForeColor = Color.White;
      lblBlk.ForeColor = Color.White;
      lblSpd.ForeColor = Color.White;
      lblAgi.ForeColor = Color.White;
      lblJum.ForeColor = Color.White;
      lblVis.ForeColor = Color.White;
      lblCon.ForeColor = Color.White;
      lbltck.ForeColor = Color.White;
      lblThr.ForeColor = Color.White;
      lblCat.ForeColor = Color.White;
      lblPun.ForeColor = Color.White;
      lblKck.ForeColor = Color.White;
      lblsta.ForeColor = Color.White;
      lblCar.ForeColor = Color.White;

      lblStr.BackColor = Color.Black;
      lblBlk.BackColor = Color.Black;
      lblSpd.BackColor = Color.Black;
      lblAgi.BackColor = Color.Black;
      lblJum.BackColor = Color.Black;
      lblVis.BackColor = Color.Black;
      lblCon.BackColor = Color.Black;
      lbltck.BackColor = Color.Black;
      lblThr.BackColor = Color.Black;
      lblCat.BackColor = Color.Black;
      lblPun.BackColor = Color.Black;
      lblKck.BackColor = Color.Black;
      lblsta.BackColor = Color.Black;
      lblCar.BackColor = Color.Black;
      #endregion

      Archetype at = cmbxPosition.SelectedItem as Archetype;
      if (at != null)
      {

        foreach (String str in at.Majors)
        {
          #region Majors
          switch (str.ToLower())
          {
            case "strength":
              lblStr.BackColor = Color.Green;
              break;
            case "blocking":
              lblBlk.BackColor = Color.Green;
              break;
            case "speed":
              lblSpd.BackColor = Color.Green;
              break;
            case "agility":
              lblAgi.BackColor = Color.Green;
              break;
            case "jumping":
              lblJum.BackColor = Color.Green;
              break;
            case "vision":
              lblVis.BackColor = Color.Green;
              break;
            case "confidence":
              lblCon.BackColor = Color.Green;
              break;
            case "tackling":
              lbltck.BackColor = Color.Green;
              break;
            case "throwing":
              lblThr.BackColor = Color.Green;
              break;
            case "catching":
              lblCat.BackColor = Color.Green;
              break;
            case "punting":
              lblPun.BackColor = Color.Green;
              break;
            case "kicking":
              lblKck.BackColor = Color.Green;
              break;
            case "stamina":
              lblsta.BackColor = Color.Green;
              break;
            case "carrying":
              lblCar.BackColor = Color.Green;
              break;
          }
          #endregion
        }

        foreach (String str in at.Minors)
        {
          #region Minors
          switch (str.ToLower())
          {
            case "strength":
              lblStr.BackColor = Color.Blue;
              break;
            case "blocking":
              lblBlk.BackColor = Color.Blue;
              break;
            case "speed":
              lblSpd.BackColor = Color.Blue;
              break;
            case "agility":
              lblAgi.BackColor = Color.Blue;
              break;
            case "jumping":
              lblJum.BackColor = Color.Blue;
              break;
            case "vision":
              lblVis.BackColor = Color.Blue;
              break;
            case "confidence":
              lblCon.BackColor = Color.Blue;
              break;
            case "tackling":
              lbltck.BackColor = Color.Blue;
              break;
            case "throwing":
              lblThr.BackColor = Color.Blue;
              break;
            case "catching":
              lblCat.BackColor = Color.Blue;
              break;
            case "punting":
              lblPun.BackColor = Color.Blue;
              break;
            case "kicking":
              lblKck.BackColor = Color.Blue;
              break;
            case "stamina":
              lblsta.BackColor = Color.Blue;
              break;
            case "carrying":
              lblCar.BackColor = Color.Blue;
              break;
          }
          #endregion
        }
      }

      if (lblStr.BackColor == Color.Black)
      {
        nmrcudStr.Value = 8;
      }
      if (lblBlk.BackColor == Color.Black)
      {
        nmrcudBlk.Value = 8;
      }
      if (lblSpd.BackColor == Color.Black)
      {
        nmrcudSpd.Value = 8;
      }
      if (lblAgi.BackColor == Color.Black)
      {
        nmrcudAgi.Value = 8;
      }
      if (lblJum.BackColor == Color.Black)
      {
        nmrcudJum.Value = 8;
      }
      if (lblVis.BackColor == Color.Black)
      {
        nmrcudVis.Value = 8;
      }
      if (lblCon.BackColor == Color.Black)
      {
        nmrcudCon.Value = 8;
      }
      if (lbltck.BackColor == Color.Black)
      {
        nmrcudTck.Value = 8;
      }
      if (lblThr.BackColor == Color.Black)
      {
        nmrcudThr.Value = 8;
      }
      if (lblCat.BackColor == Color.Black)
      {
        nmrcudCat.Value = 8;
      }
      if (lblPun.BackColor == Color.Black)
      {
        nmrcudPun.Value = 8;
      }
      if (lblKck.BackColor == Color.Black)
      {
        nmrcudKck.Value = 8;
      }
      if (lblsta.BackColor == Color.Black)
      {
        nmrcudSta.Value = 8;
      }
      if (lblCar.BackColor == Color.Black)
      {
        nmrcudCar.Value = 8;
      }
    }
    

    private void nmrcudStr_Enter(object sender, EventArgs e)
    {
      ((NumericUpDown)sender).Select(0, ((NumericUpDown)sender).Text.Length);
    }

    private void toolStripMenuItem3_Click(object sender, EventArgs e)
    {

      using (frmAbout frm = new frmAbout())
      {
        frm.ShowDialog();
      }
    }

    private void toolStripMenuItem1_Click(object sender, EventArgs e)
    {
      this.Close();
    }


    private void toolStripMenuItem2_Click(object sender, EventArgs e)
    {
      System.Diagnostics.Process p = new System.Diagnostics.Process();
      p.StartInfo.FileName = "http://www.glbwiki.com/index.php?title=Virtual_player_builder";
      p.Start();
    }
    #endregion



    private void btnEstimate_Click(object sender, EventArgs e)
    {
      Dictionary<string, GLBAttribute> PlayerAttributes = new Dictionary<string, GLBAttribute>();
      if (lblStr.BackColor == Color.Green)
        PlayerAttributes.Add("strength", new GLBAttribute("strength", (double)nmrcudStr.Value, (int)spnPctStr.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblStr.BackColor == Color.Blue)
        PlayerAttributes.Add("strength", new GLBAttribute("strength", (double)nmrcudStr.Value, (int)spnPctStr.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("strength", new GLBAttribute("strength", (double)nmrcudStr.Value, (int)spnPctStr.Value, GLBAttribute.AttributeType.atNone));


      if (lblBlk.BackColor == Color.Green)
        PlayerAttributes.Add("blocking", new GLBAttribute("blocking", (double)nmrcudBlk.Value, (int)spnPctBlk.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblBlk.BackColor == Color.Blue)
        PlayerAttributes.Add("blocking", new GLBAttribute("blocking", (double)nmrcudBlk.Value, (int)spnPctBlk.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("blocking", new GLBAttribute("blocking", (double)nmrcudBlk.Value, (int)spnPctBlk.Value, GLBAttribute.AttributeType.atNone));


      if (lblSpd.BackColor == Color.Green)
        PlayerAttributes.Add("speed", new GLBAttribute("speed", (double)nmrcudSpd.Value, (int)spnPctSpd.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblSpd.BackColor == Color.Blue)
        PlayerAttributes.Add("speed", new GLBAttribute("speed", (double)nmrcudSpd.Value, (int)spnPctSpd.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("speed", new GLBAttribute("speed", (double)nmrcudSpd.Value, (int)spnPctSpd.Value, GLBAttribute.AttributeType.atNone));


      if (lbltck.BackColor == Color.Green)
        PlayerAttributes.Add("tackling", new GLBAttribute("tackling", (double)nmrcudTck.Value, (int)spnPctTck.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lbltck.BackColor == Color.Blue)
        PlayerAttributes.Add("tackling", new GLBAttribute("tackling", (double)nmrcudTck.Value, (int)spnPctTck.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("tackling", new GLBAttribute("tackling", (double)nmrcudTck.Value, (int)spnPctTck.Value, GLBAttribute.AttributeType.atNone));

      if (lblAgi.BackColor == Color.Green)
        PlayerAttributes.Add("agility", new GLBAttribute("agility", (double)nmrcudAgi.Value, (int)spnPctAgi.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblAgi.BackColor == Color.Blue)
        PlayerAttributes.Add("agility", new GLBAttribute("agility", (double)nmrcudAgi.Value, (int)spnPctAgi.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("agility", new GLBAttribute("agility", (double)nmrcudAgi.Value, (int)spnPctAgi.Value, GLBAttribute.AttributeType.atNone));


      if (lblThr.BackColor == Color.Green)
        PlayerAttributes.Add("throwing", new GLBAttribute("throwing", (double)nmrcudThr.Value, (int)spnPctThr.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblThr.BackColor == Color.Blue)
        PlayerAttributes.Add("throwing", new GLBAttribute("throwing", (double)nmrcudThr.Value, (int)spnPctThr.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("throwing", new GLBAttribute("throwing", (double)nmrcudThr.Value, (int)spnPctThr.Value, GLBAttribute.AttributeType.atNone));


      if (lblJum.BackColor == Color.Green)
        PlayerAttributes.Add("jumping", new GLBAttribute("jumping", (double)nmrcudJum.Value, (int)spnPctJum.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblJum.BackColor == Color.Blue)
        PlayerAttributes.Add("jumping", new GLBAttribute("jumping", (double)nmrcudJum.Value, (int)spnPctJum.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("jumping", new GLBAttribute("jumping", (double)nmrcudJum.Value, (int)spnPctJum.Value, GLBAttribute.AttributeType.atNone));


      if (lblCat.BackColor == Color.Green)
        PlayerAttributes.Add("catching", new GLBAttribute("catching", (double)nmrcudCat.Value, (int)spnPctCat.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblCat.BackColor == Color.Blue)
        PlayerAttributes.Add("catching", new GLBAttribute("catching", (double)nmrcudCat.Value, (int)spnPctCat.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("catching", new GLBAttribute("catching", (double)nmrcudCat.Value, (int)spnPctCat.Value, GLBAttribute.AttributeType.atNone));


      if (lblsta.BackColor == Color.Green)
        PlayerAttributes.Add("stamina", new GLBAttribute("stamina", (double)nmrcudSta.Value, (int)spnPctSta.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblsta.BackColor == Color.Blue)
        PlayerAttributes.Add("stamina", new GLBAttribute("stamina", (double)nmrcudSta.Value, (int)spnPctSta.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("stamina", new GLBAttribute("stamina", (double)nmrcudSta.Value, (int)spnPctSta.Value, GLBAttribute.AttributeType.atNone));


      if (lblCar.BackColor == Color.Green)
        PlayerAttributes.Add("carrying", new GLBAttribute("carrying", (double)nmrcudCar.Value, (int)spnPctCar.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblCar.BackColor == Color.Blue)
        PlayerAttributes.Add("carrying", new GLBAttribute("carrying", (double)nmrcudCar.Value, (int)spnPctCar.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("carrying", new GLBAttribute("carrying", (double)nmrcudCar.Value, (int)spnPctCar.Value, GLBAttribute.AttributeType.atNone));


      if (lblVis.BackColor == Color.Green)
        PlayerAttributes.Add("vision", new GLBAttribute("vision", (double)nmrcudVis.Value, (int)spnPctVis.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblVis.BackColor == Color.Blue)
        PlayerAttributes.Add("vision", new GLBAttribute("vision", (double)nmrcudVis.Value, (int)spnPctVis.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("vision", new GLBAttribute("vision", (double)nmrcudVis.Value, (int)spnPctVis.Value, GLBAttribute.AttributeType.atNone));


      if (lblKck.BackColor == Color.Green)
        PlayerAttributes.Add("kicking", new GLBAttribute("kicking", (double)nmrcudKck.Value, (int)spnPctKck.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblKck.BackColor == Color.Blue)
        PlayerAttributes.Add("kicking", new GLBAttribute("kicking", (double)nmrcudKck.Value, (int)spnPctKck.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("kicking", new GLBAttribute("kicking", (double)nmrcudKck.Value, (int)spnPctKck.Value, GLBAttribute.AttributeType.atNone));


      if (lblCon.BackColor == Color.Green)
        PlayerAttributes.Add("confidence", new GLBAttribute("confidence", (double)nmrcudCon.Value, (int)spnPctCon.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblCon.BackColor == Color.Blue)
        PlayerAttributes.Add("confidence", new GLBAttribute("confidence", (double)nmrcudCon.Value, (int)spnPctCon.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("confidence", new GLBAttribute("confidence", (double)nmrcudCon.Value, (int)spnPctCon.Value, GLBAttribute.AttributeType.atNone));


      if (lblPun.BackColor == Color.Green)
        PlayerAttributes.Add("punting", new GLBAttribute("punting", (double)nmrcudPun.Value, (int)spnPctPun.Value, GLBAttribute.AttributeType.atPrimary));
      else if (lblPun.BackColor == Color.Blue)
        PlayerAttributes.Add("punting", new GLBAttribute("punting", (double)nmrcudPun.Value, (int)spnPctPun.Value, GLBAttribute.AttributeType.atSecondary));
      else
        PlayerAttributes.Add("punting", new GLBAttribute("punting", (double)nmrcudPun.Value, (int)spnPctPun.Value, GLBAttribute.AttributeType.atNone));
      using (EstimateLevelGains newForm = new EstimateLevelGains(PlayerAttributes, (Archetype)cmbxPosition.SelectedItem, spnedtLevel.Value, m_Archetypes))
      {
        newForm.ShowDialog(this);
      }
    }


    private void newPlayerBuildSliderToolStripMenuItem_Click(object sender, EventArgs e)
    {
      if (cmbxPosition.Text.Trim() != String.Empty)
      {
        DialogResult dr = DialogResult.Cancel;
        using (Slider frmSlider = new Slider((Archetype)cmbxPosition.SelectedItem, m_Archetypes))
        {
          if (frmSlider.ShowDialog().Equals(DialogResult.OK))
          {
            cmbxPosition.Text = frmSlider.Position;
            //Also set the proper attr values
          }
        }
      }
    }



    private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
    {

    }



  }

  public class Archetype
  {
    private String m_DisplayName = "Unknown";

    public String Position;
    public int MinHeight = 76;
    public int MaxHeight = 72;
    public int MinWeight = 180;
    public int MaxWeight = 220;
    public List<string> Majors = new List<string>();
    public List<string> Minors = new List<string>();
    public List<string> HeightPlus = new List<string>();
    public List<string> HeightMinus = new List<string>();
    public List<string> WeightPlus = new List<string>();
    public List<string> WeightMinus = new List<string>();
    public String DisplayName
    {
      get { return m_DisplayName; }
      set { m_DisplayName = value; }
    }
    public String XMLName;
    public String Link;

    public Archetype(XmlNode ATNode, String ATPosition)
    {
      Position = ATPosition;
      if (ATNode.Attributes["name"] != null)
      {
        DisplayName = ATNode.Attributes["name"].Value;
      }
      XMLName = ATNode.Name;
      foreach (XmlNode detailNode in ATNode.ChildNodes)
      {
        switch (detailNode.Name)
        {
          case "major":
            Majors.Add(detailNode.InnerText);
            break;
          case "minor":
            Minors.Add(detailNode.InnerText);
            break;
          case "pagelink":
            Link = detailNode.InnerText;
            break;
          case "htplus":
            HeightPlus.Add(detailNode.InnerText);
            break;
          case "htminus":
            HeightMinus.Add(detailNode.InnerText);
            break;
          case "wtplus":
            WeightPlus.Add(detailNode.InnerText);
            break;
          case "wtminus":
            WeightMinus.Add(detailNode.InnerText);
            break;
        }
      }
    }

  }

}